package cn.itsource.ymcc.service.impl;

import cn.itsource.dto.LoginJwtInfoDto;
import cn.itsource.result.JSONResult;
import cn.itsource.util.AssertUtil;
import cn.itsource.ymcc.doc.CourseDoc;
import cn.itsource.ymcc.domain.*;
import cn.itsource.ymcc.dto.CourseAddDto;
import cn.itsource.ymcc.feign.CommonFeignClient;
import cn.itsource.ymcc.feign.MediaFileClient;
import cn.itsource.ymcc.feign.SearchFeignClient;
import cn.itsource.ymcc.mapper.CourseMapper;
import cn.itsource.ymcc.service.*;
import cn.itsource.ymcc.util.EmailUtil;
import cn.itsource.ymcc.utils.LoginYmccContext;
import cn.itsource.ymcc.vo.Course2OrderInfoVo;
import cn.itsource.ymcc.vo.Course2OrderVo;
import cn.itsource.ymcc.vo.CourseInfoVo;
import com.alibaba.fastjson.JSON;
import com.baomidou.mybatisplus.mapper.EntityWrapper;
import com.baomidou.mybatisplus.mapper.Wrapper;
import com.baomidou.mybatisplus.service.impl.ServiceImpl;
import org.apache.rocketmq.spring.core.RocketMQTemplate;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cloud.client.ServiceInstance;
import org.springframework.cloud.client.discovery.DiscoveryClient;
import org.springframework.http.ResponseEntity;
import org.springframework.messaging.support.MessageBuilder;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.client.RestTemplate;

import javax.validation.Valid;

import java.util.*;
import java.util.function.Consumer;
import java.util.stream.Collectors;

import static com.alibaba.fastjson.JSON.*;

/**
 * <p>
 *  服务实现类
 * </p>
 *
 * @author Cherish
 * @since 2022-08-07
 */
@Service
public class CourseServiceImpl extends ServiceImpl<CourseMapper, Course> implements ICourseService {
    @Autowired
    private ITeacherService teacherService;
    @Autowired
    private ICourseDetailService courseDetailService;
    @Autowired
    private ICourseResourceService courseResourceService;
    @Autowired
    private ICourseMarketService courseMarketService;
    @Autowired
    private ICourseTeacherService courseTeacherService;
    @Autowired
    private ICourseSummaryService courseSummaryService;
    @Autowired
    private ICourseTypeService courseTypeService;
    @Autowired
    private SearchFeignClient searchFeignClient;

    @Autowired
    private CommonFeignClient commonFeignClient;

    @Autowired
    private MediaFileClient mediaFileClient;


    @Autowired
    private RocketMQTemplate mqTemplate;

    @Autowired
    private RestTemplate restTemplate;

    @Autowired
    private DiscoveryClient discoveryClient;

    @Autowired
    private ICourseChapterService courseChapterService;




    @Override
    @Transactional
    public void save(CourseAddDto courseAddDto) {
        @Valid Course course = courseAddDto.getCourse();
        @Valid CourseDetail courseDetail = courseAddDto.getCourseDetail();
        @Valid CourseMarket courseMarket = courseAddDto.getCourseMarket();
        @Valid CourseResource courseResource = courseAddDto.getCourseResource();
        @Valid List<Long> teacharIds = courseAddDto.getTeacharIds();

        check(course);

        saveCourse(course, teacharIds);

        saveCourseDetails(course, courseDetail);

        saveCoureseMarket(course, courseMarket);

        saveCourseResource(course, courseResource);

        SaveCourseSummary(course);

        saveTeachers(course, teacharIds);

        addTotalCount(course);


    }

    @Override
    @Transactional
    public void onLineCourse(Long id) {
        //===========数据库部分==============

        //1.参数校验
        AssertUtil.isNotNull(id,"课程ID为空！！");
        Course course = selectById(id);
        AssertUtil.isNotNull(course,"课程不存在！");
        boolean offLine = course.getStatus() == Course.STATE_OFF_LINE;
        AssertUtil.isTrue(offLine,"课程已上架！");
        // 2.修改课程状态，并且设置上架时间
        Date nowTime = new Date();
        course.setOnlineTime(nowTime);
        course.setStatus(Course.STATE_ON_LINE);
        //3.存入数据库
        updateById(course);

        // ============ES部分=============
        // 1.准备需要存入es中的数据
        CourseDoc courseDoc = new CourseDoc();
        BeanUtils.copyProperties(course,courseDoc);
        CourseSummary courseSummary = courseSummaryService.selectById(course.getId());
        BeanUtils.copyProperties(courseSummary,courseDoc);
        CourseMarket courseMarket = courseMarketService.selectById(course.getId());
        BeanUtils.copyProperties(courseMarket,courseDoc);
        CourseType courseType = courseTypeService.selectById(course.getCourseTypeId());
        BeanUtils.copyProperties(courseType,courseDoc);
        courseDoc.setCourseTypeName(courseType.getName());
        courseDoc.setId(course.getId());
        courseDoc.setChargeName(courseMarket.getCharge().intValue() == 1 ? "收费" : "免费");
        // 2.存入ES中
        JSONResult jsonResult = searchFeignClient.saveCourse(courseDoc);
        AssertUtil.isTrue(jsonResult.isSuccess(),"课程发布失败！");
        //System.out.println("存入成功！");

        //=========MQ部分（写死数据）===========
//        MessageEmail messageEmail = new MessageEmail();
//        messageEmail.setTitle("课程发布惹");
//        messageEmail.setContent("亲爱的用户您好，最新课程 <a href='http://course.ymcc.com:6002/detail.html?courseId=4'> java架构师班 </a> 发布啦，点击课程了解详情");
//        messageEmail.setSendTime(nowTime);
//        messageEmail.setUserId(1L);
//        mqTemplate.syncSend("email:course", JSON.toJSONString(messageEmail));
//        //从nacos中获取服务地址
//        ServiceInstance service = discoveryClient.getInstances("service-common").get(0);
//        String url = service.getHost() + ":" + service.getPort();
//        //通过restTemplate调用
//        restTemplate.postForEntity("http://" + url + "/messageEmail/save", messageEmail, JSONResult.class);
//        MessageSms messageSms = new MessageSms();
//        messageSms.setTitle("你好！");
//        messageSms.setContent("阿巴阿巴阿巴");
//        messageSms.setSendTime(nowTime);
//        mqTemplate.syncSend("sms:course", JSON.toJSONString(messageSms));
//        commonFeignClient.saveOrUpdate(messageSms);
//        MessageStation messageStation = new MessageStation();
//        messageStation.setUserId(1L);
//        messageStation.setContent("你好！");
//        messageStation.setSendTime(nowTime);
//        mqTemplate.syncSend("station:course",JSON.toJSONString(messageStation));
//        commonFeignClient.saveOrUpdate(messageStation);

    }

    @Override
    @Transactional
    public void offLineCourse(Long id) {
        // 存入数据库
        Course course = selectById(id);
        course.setStatus(0);
        updateById(course);
        // 删除ES中数据
        JSONResult jsonResult = searchFeignClient.deleteCourse(id);
        AssertUtil.isTrue(jsonResult.isSuccess(),"课程下架失败！");
    }

    @Override
    public CourseInfoVo detailInfo(Long courseId) {
        AssertUtil.isNotNull(courseId,"非法请求！");
        Course course = selectById(courseId);
        AssertUtil.isNotNull(course,"课程不存在!");

        //业务校验  不能查询出没有上架的课程
        boolean isOnLine = course.getStatus().intValue() == Course.STATE_ON_LINE;
        AssertUtil.isTrue(isOnLine,"非法数据!");

        //这里需要查询出课程数据-销售-详情-章节-老师
        CourseMarket courseMarket = courseMarketService.selectById(courseId);
        CourseDetail courseDetail = courseDetailService.selectById(courseId);

        //查询课程老师
        Wrapper<CourseTeacher> teacherWraper = new EntityWrapper<>();
        teacherWraper.eq("course_id", courseId);
        List<CourseTeacher> courseTeachers = courseTeacherService.selectList(teacherWraper);
        List<Long> teacherIds = courseTeachers.stream().map(cteacher -> cteacher.getTeacherId()).collect(Collectors.toList());
        List<Teacher> teachers = teacherService.selectBatchIds(teacherIds);

        //课程章节
        Wrapper<CourseChapter> chapterWraper = new EntityWrapper<>();
        chapterWraper.eq("course_id", courseId);
        List<CourseChapter> courseChapters = courseChapterService.selectList(chapterWraper);

        //把数据转成Map<Long,CourseChapter>结构,方便视屏得查找
        Map<Long, CourseChapter> chaptersMap = courseChapters.stream()
                .collect(Collectors.toMap(CourseChapter::getId, courseChapter -> courseChapter));

        /*
            根据课程ID  查询媒体微服务 得到课程下的所有视频
            - service-media编写controller 根据课程ID查询课程的所有视频
            - 编写ymcc-api-media Feign接口和熔断降级
            - service-course 依赖ymcc-api-media 查询视频
         */

        JSONResult jsonResult = mediaFileClient.queryByCourseId(courseId);
        AssertUtil.isTrue(jsonResult.isSuccess(),jsonResult.getMessage());
        AssertUtil.isNotNull(jsonResult.getData(),"课程信息异常，没有视频！！");
        //2.根据章节分组，并把每个章节下的视屏，放入对应的章节中
        List<MediaFile> mediaFiles = JSON.parseArray(jsonResult.getData().toString(), MediaFile.class);
        mediaFiles.stream().forEach(mediaFile -> {
            mediaFile.setFileUrl("");
            CourseChapter courseChapter = chaptersMap.get(mediaFile.getChapterId());
            courseChapter.getMediaFiles().add(mediaFile);
        });
//        for (MediaFile mediaFile : mediaFiles) {
//            CourseChapter courseChapter = chaptersMap.get(mediaFile.getChapterId());
//            courseChapter.getMediaFiles().add(mediaFile);
//        }
        return new CourseInfoVo(course,courseDetail,courseMarket,teachers,courseChapters);
    }

    @Override
    public Course2OrderInfoVo course2OrderInfo(String courseIds) {
        AssertUtil.isNotEmpty(courseIds,"非法请求");
        String[] ids = courseIds.split(",");
        List<Course> courses = selectBatchIds(Arrays.asList(ids));
        Course2OrderInfoVo orderInfoVo = new Course2OrderInfoVo();
        List<Course2OrderVo> courseInfos = new ArrayList<>();
        courses.forEach(course -> {
            boolean isOnLine = course.getStatus() == Course.STATE_ON_LINE;
            AssertUtil.isTrue(isOnLine,"课程非法！！");
            CourseMarket courseMarket = courseMarketService.selectById(course.getId());
            courseInfos.add(new Course2OrderVo(course,courseMarket));
            orderInfoVo.setTotalAmount(orderInfoVo.getTotalAmount().add(courseMarket.getPrice()));
        });
        orderInfoVo.setCourseInfos(courseInfos);
        return orderInfoVo;
    }


    private void addTotalCount(@Valid Course course) {
        CourseType courseType = courseTypeService.selectById(course.getCourseTypeId());
        AssertUtil.isNotNull(courseType,"课程类型不存在");
        courseType.setTotalCount(courseType.getTotalCount() + 1);
        courseTypeService.updateById(courseType);
    }

    private void saveTeachers(@Valid Course course, @Valid List<Long> teacharIds) {
        teacharIds.stream().forEach(id -> {
            CourseTeacher courseTeacher = new CourseTeacher();
            courseTeacher.setCourseId(course.getId());
            courseTeacher.setTeacherId(id);
            courseTeacherService.insert(courseTeacher);
        });
    }

    private void SaveCourseSummary(@Valid Course course) {
        CourseSummary courseSummary = new CourseSummary();
        courseSummary.setId(course.getId());
        courseSummaryService.insert(courseSummary);
    }

    private void saveCourseResource(@Valid Course course, @Valid CourseResource courseResource) {
        courseResource.setCourseId(course.getId());
        courseResourceService.insert(courseResource);
    }

    private void saveCoureseMarket(@Valid Course course, @Valid CourseMarket courseMarket) {
        courseMarket.setId(course.getId());
        courseMarketService.insert(courseMarket);
    }

    private void saveCourseDetails(@Valid Course course, @Valid CourseDetail courseDetail) {
        courseDetail.setId(course.getId());
        courseDetailService.insert(courseDetail);
    }

    private void saveCourse(@Valid Course course, @Valid List<Long> teacharIds) {
        LoginJwtInfoDto loginContext = LoginYmccContext.getLoginContext();
        Long loginId = loginContext.getId();
        String loginUserName = loginContext.getUsername();
        course.setLoginId(loginId);
        course.setLoginUserName(loginUserName);
        course.setStatus(0);
        List<Teacher> teachers = teacherService.selectBatchIds(teacharIds);
        String names = teachers.stream().map(name -> name.getName()).collect(Collectors.joining(","));
        course.setTeacherNames(names);
        insert(course);
    }

    private void check(@Valid Course course) {
        Wrapper<Course> wrapper = new EntityWrapper<>();
        wrapper.eq("name", course.getName());
        Course courseTmp = selectOne(wrapper);
        AssertUtil.isNull(courseTmp,"课程已经存在！");
    }
}
